package com.ruoyi.utils;

/**
 * @description: 分库分表定位工具类 根据tenantId确定数据存储在哪个数据库和表中
 * @author: xukaihang
 * @date: 2025/9/18
 */
public class TenantShardingUtils {
    private static final int DATABASE_COUNT = 2;
    private static final int TABLE_COUNT = 32;

    /**
     * 根据tenantId计算应该存储的数据库名称
     *
     * @param tenantId 租户ID
     * @return 数据库名称 (ds0 或 ds1)
     */
    public static String getDatabaseName(Long tenantId) {
        if (tenantId == null) {
            return "ds0";
        }

        // 计算tenantId除以64的余数
        int remainder = (int) (Math.abs(tenantId) % 64);
        // 根据余数判断应该路由到哪个库
        if (remainder < 32) {
            return "ds0";
        } else {
            return "ds1";
        }
    }

    /**
     * 根据tenantId计算应该存储的表后缀
     *
     * @param tenantId 租户ID
     * @return 表后缀 (0-31)
     */
    public static int getTableIndex(Long tenantId) {
        if (tenantId == null) {
            return 0;
        }

        return (int) (Math.abs(tenantId) % TABLE_COUNT);
    }

    /**
     * 根据逻辑表名和tenantId计算实际表名
     *
     * @param logicTableName 逻辑表名
     * @param tenantId       租户ID
     * @return 实际表名
     */
    public static String getActualTableName(String logicTableName, Long tenantId) {
        if (logicTableName == null || logicTableName.isEmpty()) {
            throw new IllegalArgumentException("逻辑表名不能为空");
        }

        return logicTableName + "_" + getTableIndex(tenantId);
    }

    /**
     * 根据tenantId计算应该存储的哪个表
     *
     * @param tenantId 租户ID
     * @return 表名称 (0-31)
     */
    public static String getDataTableName(Long tenantId) {
        if (tenantId == null) {
            return "iot_device_0"; // 默认表
        }

        int index = Math.abs(tenantId.intValue()) % 32;
        return "iot_device_" + index;
    }

    public static void main(String[] args) {
        // 参数：tenantId 确实保存哪个库，哪个表
        System.out.println("数据实际存储库：" + getDatabaseName(296L));
        System.out.println("数据实际存储表：" + getDataTableName(296L));
    }
}
